/**
 * This gets information from the Sensor, then feeds this to the VitalSignListener
 * 
 * This will be put into a buffer to shoot them out to the local Bedside Monitor
 * and the nurses station Vital Sign Listener (Which will handle it on its own)
 */
package bedside;

import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.Date;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import common.AlarmReceiver;
import common.VitalSignUpdate;

public class VitalSign implements Serializable {
	
	//Class Constants
	public static final int HEART = 0;
	public static final int LUNGS = 1;
	public static final int BP = 2;
	public static final int OX = 3;

	// Sensor alarm limits
	private int myAlarmHighHigh;
	private int myAlarmHigh;
	private int myAlarmLow;
	private int myAlarmLowLow;
	
	// Sensor input scaling
	private int myScalerHigh;
	private int myScalerLow;
	
	// Variables
	Sensor mySensor;
	VitalSignBuffer myBuffer;
	int myType;
	Alarm myAlarm = null;
	
	
	/**
	 * Constructor
	 */
	public VitalSign(int alarmLowLow,
					 int alarmLow, int alarmHigh, int alarmHighHigh,
					 int theSensorPullPeriod, int whichType){
		
		// Create sensor and vital sign buffer
		mySensor = new SteadySensor();
		//myBuffer = new VitalSignBuffer();
		
		
		
		// Set Local Alarm Limits
		myAlarmHighHigh = alarmHighHigh;
		myAlarmHigh = alarmHigh;
		myAlarmLow = alarmLow;
		myAlarmLowLow = alarmLowLow;
		
		//Set the type of Vital Sign
		myType = whichType;
		
		//LIst of Alarm Recievers that need to know about this alarm
		 myAlarm = new Alarm();
		
		
		// Schedule the buffer to transmit its contents at a fixed interval.
		Timer sendTimer = new Timer("VitalSign Update Caller", true );
		TimerTask task = new TimerTask() {
			@Override
			public void run() {
				VitalSign.this.update();
			}
		};
		sendTimer.scheduleAtFixedRate(task, 0, theSensorPullPeriod);
		
	}
	
	/**
	 * Set the buffer that the vitals are pushed too
	 * @param theBuffer
	 */
	public void setVitalSignBuffer( VitalSignBuffer theBuffer ){
		myBuffer = theBuffer;
	}
	
	/**
	 * Pulls a new vital from the sensor
	 */
	public void update(){
		//Local Variables
		int rawReading = mySensor.getVital();
		String reading = scale( rawReading );
		
		//IF This Reading is Alarm worthy
		if(rawReading < this.myAlarmLow){
			if(rawReading <= this.myAlarmLowLow){
				myAlarm.setState(Alarm.LOW_LOW);
			}
			else{ //Must be between the two limits

				myAlarm.setState(Alarm.LOW);				
			}
		}
		else if (rawReading > this.myAlarmHigh) {
			if(rawReading >= this.myAlarmHighHigh){

				myAlarm.setState(Alarm.HIGH_HIGH);
			}
			else { //Must be between the two limits

				myAlarm.setState(Alarm.HIGH);
			}
			
		}
		
		
		// Create a vital sign update and sent it to the 
		// Vital sign buffer
		VitalSignUpdate update = new VitalSignUpdate(this, new Date(), reading);
		
		try {
			myBuffer.updateVitalSign(update);
			
			
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			System.out.println( "CLASS: VitalSign METHOD: update EXCEPTION:" + e.getMessage() );
			e.printStackTrace();
		}
		
	}
	
	/**
	 * Scales the sensor reading
	 */
	public String scale(int reading){
		//Local Constants
		
		//Local Variables
		String retVal = "";
		float x, y;  //Will be used for scaling
		Random gen = new Random();
		
		/*************main body**************/
		
		// Scale the sensor reading according to type
		switch(myType){
			case(VitalSign.HEART):
				y = gen.nextInt(2) + 1;
				x = 2;
				retVal = Integer.toString((int)((reading * x) + y));
				break;
			case(VitalSign.BP):
				x = 2.25f;
				y = 1.67f;
				x = (int)(float)Math.floor(reading * x);
				y = (int)(float)Math.floor(reading * y);
				retVal = Float.toString(x) + "/" + Float.toString(y);
				break;
			case(VitalSign.LUNGS):
				x = 3f/5f;
				retVal = Integer.toString((int)((float)reading * x));
				break;
			case(VitalSign.OX):
				retVal = Integer.toString(reading);
				break;
		
		}
		
		
		
		return retVal;
	}
	
	/**
	 * This is done to expose the alarm for Nurses to reset it
	 * @return
	 */
	public void fixAlarm(){
		myAlarm.setState(Alarm.NORMAL);
	}
	
	/**
	 * 
	 * @return
	 */
	public String getType(){
		String retVal = "";
		
		switch(myType){
		case(VitalSign.HEART):
			retVal = "Heart";
			break;
		case(VitalSign.BP):
			retVal = "Blood Pressure";
			break;
		case(VitalSign.LUNGS):
			retVal = "Respiration";
			break;
		case(VitalSign.OX):
			retVal = "Blood Oxygen Level";
			break;
		}
		return retVal;
	}
	
	public void register(AlarmReceiver newItem){
		this.myAlarm.register(newItem);
	}
	public void unRegister(AlarmReceiver takeMe){
		this.myAlarm.unRegister(takeMe);
	}
	
	public void setLimits (int lowlow, int low, int high, int highhigh){
		myAlarmHighHigh = highhigh;
		myAlarmHigh = high;
		myAlarmLow = low;
		myAlarmLowLow = lowlow;
	}
	
}
